package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateSearchServiceImpl implements IStrategyTemplateSearchService {
    @Autowired
    private StrategyTemplateRepository repository;

    public void saveOrUpdate(StrategyTemplate template) {
        repository.save(template);
    }

    private List<StatisVO> statisGroup(String idField,String nameField,String groupName,BoolQueryBuilder query) {
        //分组维度集合对象
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        //第一个分组维度封装对象:idField
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id"); //别名id
        idSource.field(idField);  //字段themeId
        idSource.missingBucket();   //忽略不满足条件的bucket
        sources.add(idSource);

        //第二个分组维度封装对象:nameField
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name"); //别名name
        nameSource.field(nameField);  //字段themeName
        nameSource.missingBucket();     //忽略不满足条件的bucket
        sources.add(nameSource);

        //聚合查询，分组名称为groupName
        CompositeAggregationBuilder aggBuilder = new CompositeAggregationBuilder(groupName, sources);

        //查询语句封装对象
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(query);                              //查询条件
        builder.withIndices(StrategyTemplate.INDEX_NAME);      //索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);         //类型
        builder.addAggregation(aggBuilder);                    //聚合查询构建模块
        builder.withPageable(PageRequest.of(0, 1)); //jpa规范中page不允许pagesize为0

        //执行查询操作
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        //从查询结果数据中获取聚合相关的数据
        InternalComposite aggregation = page.getAggregations().get(groupName);
        StatisVO vo = null;
        List<StatisVO> list = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            if(bucket.getKey().get("id") != null){
                vo = new StatisVO();
                vo.setId(Long.parseLong(bucket.getKey().get("id").toString()));
                vo.setName(bucket.getKey().get("name").toString());
                vo.setCount(bucket.getDocCount());
                list.add(vo);
            }
        }
        //集合根据count从大到小排序
        list.sort(new Comparator<StatisVO>() {
            public int compare(StatisVO o1, StatisVO o2) {
                return (int)(o2.getCount() - o1.getCount());
            }
        });
        return list;
    }

    public List<StatisVO> queryCondition(int condition) {
        if(condition == SearchQueryObject.CONDITION_TYPE_ABROAD){   //按国外的国家分类
            return statisGroup("countryId","countryName","countryGroup",null);
        }else if(condition == SearchQueryObject.CONDITION_TYPE_UN_ABROAD){  //按国内省份分类
            BoolQueryBuilder query = new BoolQueryBuilder();
            query.mustNot(QueryBuilders.termQuery("country",1));
            return statisGroup("provinceId","provinceName","provinceGroup",query);
        }else if(condition == SearchQueryObject.CONDITION_TYPE_THEME){  //按主题分类
            return statisGroup("themeId","themeName","themeGroup",null);
        }
        return null;
    }

    public List<Map<String, Object>> queryThemeCommend() {
        //按主题分类查出所有的攻略vo对象
        List<StatisVO> voList = this.statisGroup("themeId", "themeName", "themeGroup", null);
        //如果vo对象个数大于10，只取前十个
        if(voList.size() >10){
            voList.subList(0, 10);
        }
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map = null;
        for (StatisVO vo : voList) {
            map = new HashMap<>();
            map.put("theme", vo);
            map.put("dests",this.getDestByThemeId(vo.getId()));
            list.add(map);
        }
        return list;
    }

    public Page<StrategyTemplate> query(SearchQueryObject qo) {
        //分页对象
        PageRequest pageable = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.by(Sort.Direction.DESC, qo.getOrderBy()));
        //查询条件对象
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if (qo.getType() != -1 && qo.getTypeValue() != -1){    //当有类型分类和条件类别的时候才拼接条件
            if(qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD){
                //如果是海外查询，以国家查询
                query.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
            }else if( qo.getType() == SearchQueryObject.CONDITION_TYPE_UN_ABROAD){
                //如果是国内查询，以省份查询
                query.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
            }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME){
                //如果是主题查询，以主题的id查询
                query.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
            }
        }
        //按分页条件和查询条件查询出结果
        Page<StrategyTemplate> page = repository.search(query, pageable);
        return page;
    }

    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);
    }

    private List<StatisVO> getDestByThemeId(Long id) {
        //根据themeId查询所有的数据
        Iterable<StrategyTemplate> iterable = repository.search(QueryBuilders.termQuery("themeId", id));
        List<StatisVO> list = new ArrayList<>();
        //用来去除重复
        List<String> nameList = new ArrayList<>();
        //遍历数据
        iterable.forEach(st ->{
            //如果还未包含该数据，则放入集合中
          if(!nameList.contains(st.getDestName())){
              StatisVO vo = new StatisVO();
              vo.setId(st.getDestId());
              vo.setName(st.getDestName());
              list.add(vo);
                nameList.add(st.getDestName());
            }
        });
        return list;
    }
}
